package com.hpe.wx.performance.redis.service;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ReflectionException;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hpe.wx.performance.redis.dao.PerformanceDao;
import com.hpe.wx.performance.redis.utils.JMXUtils;
import com.hpe.wx.performance.redis.utils.MyMD5Util;

import redis.clients.jedis.Tuple;

@Service
public class PerformanceServiceImpl implements PerFormanceService {
	private static Logger logger = Logger.getLogger(PerformanceServiceImpl.class.getSimpleName());
	
	@Autowired
	private PerformanceDao dao;

	@Override
	public Long zAddData(String key, double score, String member) {
		return dao.zAdd(key, score, member);
	}

	@Override
	public List<String> getDataListByIndex(String key, long indexStart, long indexEnd, int orderBy) {
		Set<Tuple> dataSet = dao.getSortedSetByIndex(key, indexStart, indexEnd, orderBy);
		List<String> res = new ArrayList<>();
		for (Tuple tuple : dataSet) {
			String member = tuple.getElement().split(":")[0];
			double score = tuple.getScore();
			res.add(member);
		}
		return res;
	}

	@Override
	public List<String> getTimeStamp(String jmxUrl, String key, int orderBy) {
		// String key, long indexStart, long indexEnd
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Object> getDataListByScore(String key, double scoreStart, double scoreEnd, int orderBy) {
		Set<Tuple> dataSet = dao.getSortedSetByScore(key, scoreStart, scoreEnd, orderBy);
		// Set<Tuple> dataSet = dao.getSortedSetByIndex(key, 0, -1, orderBy);
		List<Object> res = new ArrayList<>();
		for (Tuple tuple : dataSet) {
			Object data = Double.parseDouble(tuple.getElement().split(":")[0]);
			double score = tuple.getScore();
			res.add(data);
		}
		return res;
	}

	@Override
	public List<Double> getTimeDataListByScore(String key, double scoreStart, double scoreEnd, int orderBy) {
		Set<Tuple> dataSet = dao.getSortedSetByScore(key, scoreStart, scoreEnd, orderBy);
		// dao.getSortedSetByIndex(key,0 ,-1, orderBy);
		List<Double> res = new ArrayList<>();
		for (Tuple tuple : dataSet) {
			// String member = tuple.getElement().split(":")[0];
			double score = tuple.getScore();
			// if(scoreStart < score && score < scoreEnd ){
			res.add(score);
			// }
		}
		return res;
	}

	public Set<Tuple> getAllJMXURLs() {
		Set<Tuple> urls = dao.getSortedSetByScore("JMXURL", "-inf", "+inf", 0);
		// dao.getSortedSetByIndex("JMXURL", 0, -1, 0);
		logger.info("###" + "get jmxUrls from redis, and the size is " + urls.size());
		return urls;
	}

	public void addJMXURL(String jmxUrl) {
		// Set<Tuple> urls = dao.getSortedSetByIndex("JMXURL", 0, 0, 1);
		Date now = new Date();
		long score = now.getTime();
		dao.zAdd("JMXURL", score, jmxUrl);
	}

	public void removeJMXURL(String jmxUrl) {
		dao.zRemove("JMXURL", jmxUrl);
	}

	@Override
	public void addDate2Redis(String jmxUrl) throws MalformedObjectNameException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException {
		String printLog = "";
		String md5jmxUrl = MyMD5Util.string2MD5(jmxUrl);
		long currentTimeStamp = (new Date()).getTime();

		// System Datas cpu and memery
		DecimalFormat df = new DecimalFormat("0.00");
		Map<String, Number> sysInfo = JMXUtils.getOperatingSystemInfo(jmxUrl, null, null);

		Long totalPhysicalMemorySize = (Long) sysInfo.get("TOTALPHYSICALMEMORYSIZE");
		Long freePhysicalMemorySize = (Long) sysInfo.get("FREEPHYSICALMEMORYSIZE");
		Double systemCpuLoad = (Double) sysInfo.get("SYSTEMCPULOAD") * 100;

		String cpuper = df.format(systemCpuLoad);
		String memper = df.format((1 - freePhysicalMemorySize * 1.0 / totalPhysicalMemorySize) * 100);

		// heap and jvm Datas
		Map<String, Number> heapInfo = JMXUtils.getHeapInfo(jmxUrl, null, null);

		// long init = (Long) heapInfo.get("init");
		// long max = (Long) heapInfo.get("max");
		long committed = (Long) heapInfo.get("committed") / 1024 / 1024;
		long used = (Long) heapInfo.get("used") / 1024 / 1024;

		String jvmper = df.format(used * 1.0 / committed * 100);

		// cpu
		zAddData("CPU:" + md5jmxUrl, currentTimeStamp, cpuper + ":" + currentTimeStamp);
		printLog += (currentTimeStamp + "###cpuUsed: " + cpuper);

		// mem
		zAddData("MEM:" + md5jmxUrl, currentTimeStamp, memper + ":" + currentTimeStamp);
		printLog += ("###memPer: " + memper);

		// jvm
		zAddData("JVM:" + md5jmxUrl, currentTimeStamp, "" + jvmper + ":" + currentTimeStamp);
		printLog += ("###jvmPer: " + jvmper);

		// heap used
		zAddData("HEAPUSED:" + md5jmxUrl, currentTimeStamp, "" + used + ":" + currentTimeStamp);
		printLog += ("###used: " + used);

		// heap committed
		zAddData("HEAPCOMMITTED:" + md5jmxUrl, currentTimeStamp, "" + committed + ":" + currentTimeStamp);
		printLog += ("###committed: " + committed);

		// timestamp
		zAddData("TIMESTAMP:" + md5jmxUrl, currentTimeStamp, currentTimeStamp + ":TIMESTAMP");
		printLog += ("###TIMESTAMP: " + currentTimeStamp);

		logger.info(printLog);

	}

	@Override
	public Long removeKey(String key) {
		return dao.remove(key);
	}

	@Override
	public Long lAddData(String key, String value) {
		Long res = dao.lPush(key, value);
		return res;
	}

	@Override
	public List<String> lGetDataListByIndex(String key, int indexStart, int indexEnd, int orderBy) {
		List<String> temp = dao.lGet(key, 0, -1);
		List<String> res = new ArrayList<>();
		for (String t : temp) {
			String[] s = t.split(":");
			Long timeStamp = Long.parseLong(s[1]);
		}
		return res;
	}

	@Override
	public List<String> lGetTimeStamp(String jmxUrl, String key, int orderBy) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<String> lGetDataListByScore(String key, int indexStart, int indexEnd, int orderBy) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Set<Tuple> lGetAllJMXURLs() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void lAddDate2Redis(String jmxUrl) {
		// TODO Auto-generated method stub

	}

	@Override
	public void lAddJMXURL(String jmxUrl) {
		// TODO Auto-generated method stub

	}

	@Override
	public void lRemoveJMXURL(String jmxUrl) {
		// TODO Auto-generated method stub

	}

	@Override
	public Long lRemoveKey(String key) {
		// TODO Auto-generated method stub
		return null;
	}

}
